home *** CD-ROM | disk | FTP | other *** search
/ Super PC 34 / Super PC 34 (Shareware).iso / spc / UTIL / DJGPP2 / V2MISC / CSDPMI1S.ZIP / SRC / CWSDPMI / TABLES.ASM < prev    next >
Encoding:
Assembly Source File  |  1996-01-18  |  10.6 KB  |  450 lines

  1. ; Copyright (C) 1995 CW Sandmann (sandmann@clio.rice.edu) 102 Hurst Ct, Destrehan, LA 70047
  2. ; Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  3. ;
  4. ; This file is distributed under the terms listed in the document
  5. ; "copying.cws", available from CW Sandmann at the address above.
  6. ; A copy of "copying.cws" should accompany this file; if not, a copy
  7. ; should be available from where this file was obtained.  This file
  8. ; may not be distributed without a verbatim copy of "copying.cws".
  9. ;
  10. ; This file is distributed WITHOUT ANY WARRANTY; without even the implied
  11. ; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  12.  
  13.     title    tables
  14.     include segdefs.inc
  15.     include tss.inc
  16.     include gdt.inc
  17.  
  18. ;------------------------------------------------------------------------
  19.  
  20.     start_data16
  21.  
  22.     extrn    _tss_ptr:word
  23.     extrn    _was_exception:byte
  24.     extrn    _hard_master_lo:byte
  25.     extrn    _npx:byte
  26.     extrn    _DPMIsp:word
  27.  
  28. has_error    db    1,0,1,1,1,1,1,0
  29.  
  30.     end_data16
  31.  
  32. ;------------------------------------------------------------------------
  33.  
  34.     start_bss
  35.  
  36.     public    _i_tss
  37. _i_tss    label    tss_s
  38.     db    type tss_s dup (?)
  39.  
  40. ivec_number    dw    ?
  41.  
  42.     extrn    _locked_stack:dword
  43.     extrn    _locked_count:byte
  44.     extrn    _user_interrupt_handler:fword
  45.     extrn    _dpmisim_regs:dword
  46.     end_bss
  47.  
  48. ;------------------------------------------------------------------------
  49.  
  50.     start_code16
  51.     extrn    _user_interrupt_return:near
  52.  
  53. ; Code size reduction (improved) by Morten Welinder
  54.  
  55.     public    _ivec0, _ivec1
  56. ;    align    4        ; fix segdefs
  57. _ivec0:
  58.     push    ds        ; 1 byte
  59.     call    ivec_common    ; 3 bytes
  60. _ivec1:
  61. rept 255
  62.     push    ds        ; 1 byte
  63.     call    ivec_common    ; 3 bytes
  64. endm
  65.  
  66. ivec_common:
  67.     push    g_pdata
  68.     pop    ds
  69.     pop    ivec_number
  70.     sub    ivec_number, offset _ivec1    ; pushes address *after* call
  71.     shr    ivec_number, 2
  72.     pop    ds
  73.     jmpt    g_itss            ; macro for jump to task segment itss
  74.  
  75. ; Task set up with ds = g_rdata, interrupts disabled
  76.     public    _interrupt_common
  77. _interrupt_common:
  78.     mov    bx,_tss_ptr
  79.     mov    ax,ivec_number
  80.     mov    [bx].tss_irqn,al
  81.     mov    esi,[bx].tss_esp
  82.     mov    fs,[bx].tss_ss        ; fs:esi -> stack
  83.     cmp    al,15
  84.     ja    short has_no_error
  85.     sub    al,8
  86.     jb    short has_no_error
  87.     mov    di,ax            ; DI has the IRQ value now
  88.     cmp    has_error[di],0
  89.     je    short check_SW_int
  90.     mov    ax,fs:[esi+8]
  91.     and    ah,30h            ; Flags IOPL if SW int, CS if exception
  92.     cmp    ah,30h
  93.     je    check_SW_int        ; We don't have selectors this large !
  94.     mov    eax,fs:[esi]
  95.     mov    [bx].tss_error,eax
  96.     add    esi,4
  97.     mov    eax,cr2            ; For page faults
  98.     mov    [bx].tss_cr2,eax
  99.     jmp    short has_no_error
  100. check_SW_int:
  101.     lgs    edi,fs:[esi]        ; CS:EIP -> GS:EDI
  102.     mov    ax,gs:[edi-2]        ; Get two bytes before; Int 0x??
  103.     cmp    al,0cdh            
  104.     jne    short has_no_error
  105.     cmp    [bx].tss_irqn,ah
  106.     jne    short has_no_error    ; Not a SW interrupt
  107.     mov    cx,di
  108.     add    cl,_hard_master_lo    ; SW int in range 8-15 redirected
  109.     mov    [bx].tss_irqn,cl    
  110. has_no_error:
  111.     mov    eax,fs:[esi]        ; eip
  112.     mov    [bx].tss_eip,eax
  113.     mov    eax,fs:[esi+8]
  114.     mov    [bx].tss_eflags,eax
  115.     mov    ax,fs:[esi+4]
  116.     mov    cx,[bx].tss_cs
  117.     mov    [bx].tss_cs,ax
  118.     add    esi,12
  119.     xor    ax,cx            ; Are low 3 bits equal?
  120.     test    al,3            ; Our CPL = 0; is their CS RPL ?
  121.     jz    short same_privilege
  122.     mov    ax,fs:[esi+4]        ; saved SS
  123.     mov    [bx].tss_ss,ax
  124.     mov    esi,fs:[esi]        ; saved SP
  125. same_privilege:
  126.     mov    [bx].tss_esp,esi    ; store corrected stack pointer
  127.     mov    _was_exception,1
  128.     xor    eax,eax
  129.     mov    fs,ax            ; just in case it becomes invalid!
  130.     mov    gs,ax            ; just in case it becomes invalid!
  131.     mov    cr2,eax            ; so we can tell INT 0E from page fault
  132.     jmpt    g_ctss            ; pass control back to real mode
  133.     jmp    _interrupt_common    ; it's a task
  134.  
  135. ; Task set up with ds = g_rdata, interrupts disabled
  136.     public    _double_fault
  137. _double_fault:
  138.     mov    bx,_tss_ptr
  139.     mov    [bx].tss_irqn,8        ; double fault
  140.     pop    [bx].tss_error        ; dword
  141.     mov    _was_exception,1
  142.     jmpt    g_ctss
  143.     jmp    short _double_fault
  144.  
  145. ;------------------------------------------------------------------------
  146. ;    This code takes HW interrupts which must be handled at Ring 0 to
  147. ;    make sure the stack is valid and converts them to Ring 3 user 
  148. ;    interrupt handlers on the locked stack.  This code assumes a 
  149. ;    ring transition (since we run with interrrupts disabled at our 
  150. ;    ring 0 code) but probably should be fixed to jump to the ivec
  151. ;    handler in that case.
  152.  
  153.     public    _irq0, _irq1
  154. ;    align    4        ; fix segdefs
  155.  
  156. irq    macro    n
  157.     push    n            ; 2 bytes
  158.     jmp    short irq_common    ; 2 bytes
  159.     endm
  160. _irq0:
  161.     irq    0
  162. _irq1:
  163.     x=6
  164.     rept 15
  165.      irq    x
  166.      x=x+6
  167.     endm
  168.  
  169. irq_common:
  170. IF run_ring EQ 0
  171. ; Interrupts are disabled; the 32-bit IRET 3 dwords (and irq#) on the stack.
  172. ; Copy it to the locked stack adding the 2 stack dwords or move it down.
  173. ; user_interrupt_return emulates an IRET changing stacks on the same ring.
  174.     push    ds
  175.     push    g_pdata
  176.     pop    ds
  177.  
  178.     cmp    _locked_count,0        ; If on locked stack, OK
  179.     jne    short already_locked
  180.     mov    dword ptr _locked_stack+4064,edi    ;Save edi
  181.     lea    edi,_locked_stack+4064    ; Locked stack - 20 - 12
  182.     mov    [edi+4],eax        ; saved eax
  183.     mov    eax,[esp]        ; ds/irq
  184.     mov    [edi+8],eax
  185.     mov    eax,[esp+4]        ; offset
  186.     mov    [edi+12],eax
  187.     mov    eax,[esp+8]        ; selector
  188.     mov    [edi+16],eax
  189.     mov    eax,[esp+12]        ; flags
  190.     mov    [edi+20],eax
  191.     lea    eax,[esp+16]
  192.     mov    [edi+24],eax
  193.     mov    [edi+28],ss
  194.     mov    ax,ds
  195.     mov    ss,ax
  196.     mov    esp,edi            ; Now on locked stack
  197.     pop    edi
  198.     jmp    short @f1
  199. already_locked:
  200.     sub    esp,8            ; Room for ESP:SS
  201.     push    eax
  202.     mov    eax,[esp+12]
  203.     mov    [esp+4],eax        ; ds/irq
  204.     mov    eax,[esp+16]
  205.     mov    [esp+8],eax        ; offset
  206.     mov    eax,[esp+20]
  207.     mov    [esp+12],eax        ; selector
  208.     mov    eax,[esp+24]
  209.     mov    [esp+16],eax        ; flags
  210.     lea    eax,[esp+28]
  211.     mov    [esp+20],eax
  212.     mov    [esp+24],ss
  213. @f1:
  214.     inc    _locked_count
  215. ;    At this point we have two dwords on new stack
  216.     sub    esp,24
  217.     mov    eax,[esp+24]
  218.     mov    [esp],eax        ; saved eax
  219.     mov    eax,[esp+28]
  220.     mov    [esp+4],eax        ; saved ds/irq
  221.  
  222.     mov    dword ptr [esp+20],offset _TEXT:_user_interrupt_return
  223.     mov    word ptr [esp+24],g_pcode
  224.     mov    dword ptr [esp+28],3002h
  225.  
  226.     xchg    bx,[esp+6]        ; IRQ # times size in BX
  227.     mov    eax,dword ptr _user_interrupt_handler[bx]
  228.     mov    dword ptr [esp+8],eax
  229.     mov    ax,word ptr _user_interrupt_handler[bx+4]
  230.     mov    word ptr [esp+12],ax
  231.     mov    dword ptr [esp+16],3002h
  232.  
  233.     pop    eax
  234.     pop    ds
  235.     pop    bx
  236.     iretd
  237. ELSE
  238. ; Our stack will be ring 0 at end of TSS after ring change; interrupts are 
  239. ; disabled.  We have the 32-bit ring change IRET structure on the stack.
  240. ; Copy it to the ring 3 stack; user_interrupt_return emulates an IRET 
  241. ; changing stacks on the same ring.
  242.     push    bp
  243.     mov    bp,sp
  244.     push    ds
  245.     push    es
  246.  
  247.     push    esi
  248.     push    edi
  249.     push    ecx
  250.  
  251.     push    g_pdata
  252.     pop    ds
  253.  
  254.     cmp    _locked_count,0        ; If on locked stack, OK
  255.     jne    short already_locked
  256.     lea    edi,_locked_stack+4076    ; Locked stack - 20
  257.     push    g_pdata
  258.     pop    es
  259.     jmp    short @f1
  260. already_locked:
  261.     mov    edi,[bp+16]        ; Saved ESP
  262.     mov    es,[bp+20]        ; Saved SS
  263.     sub    edi,20            ; Make room on current locked stack
  264. @f1:
  265.     inc    _locked_count
  266.     mov    ecx,5            ; 20 bytes
  267.     movzx    esi,bp
  268.     add    si,4            ; SS:ESI (adjust for local pushes)
  269.     cld
  270.     rep    movs dword ptr es:[edi],dword ptr ss:[esi]    ;ecx count
  271.     sub    edi,32            ; 20 bytes + 12 more for iret frame
  272.     mov    dword ptr es:[edi+8],3002h
  273.     mov    word ptr es:[edi+4],g_pcode
  274.     mov    dword ptr es:[edi],offset _TEXT:_user_interrupt_return
  275.     
  276.     xchg    bx,[bp+2]        ; IRQ # times size in BX
  277.     mov    ecx,dword ptr _user_interrupt_handler[bx]
  278.     mov    dword ptr [bp+4],ecx
  279.     mov    cx,word ptr _user_interrupt_handler[bx+4]
  280.     mov    word ptr [bp+8],cx
  281.     mov    word ptr [bp+12],3002h
  282.     mov    dword ptr [bp+16],edi    ; The new ESP
  283.     mov    word ptr [bp+20],es    ; The new SS
  284.  
  285.     pop    ecx
  286.     pop    edi
  287.     pop    esi
  288.     pop    es
  289.     pop    ds
  290.     pop    bp
  291.     pop    bx
  292.     iretd
  293. ENDIF
  294.  
  295. IFDEF I31PROT
  296. extrn _i_31prot:near
  297.  
  298. ; Note for later: since we may be changing descriptors we should make sure that
  299. ; all segment registers are reloaded.  Ones that are no longer valid are zeroed.
  300.  
  301.     public    _ivec31
  302. _ivec31:
  303.     cmp    ah,3
  304.     jne    _ivec0 + 31h * (_ivec1 - _ivec0)
  305.     cmp    al,2
  306.     jg    _ivec0 + 31h * (_ivec1 - _ivec0)
  307. ; Real mode call - ES:EDI points to structure
  308. ; Set up DS:ESI to point to their copy, ES:EDI to ours
  309.     push    ds es esi edi ecx
  310.     push    es
  311.     pop    ds
  312.     mov    esi,edi
  313.     mov    cx,g_pdata
  314.     mov    es,cx
  315.     mov    edi,offset DGROUP:_dpmisim_regs
  316.     mov    ecx,25
  317.     cld
  318.     rep    movs word ptr es:[edi],word ptr ds:[esi]
  319.     pop    ecx edi esi es ds
  320.     jmp    _ivec0 + 31h * (_ivec1 - _ivec0)
  321.  
  322. ; This is where we return to restore the register structure
  323. ; Because of a bug in GO32 V1.10 & V1.11, we can't touch the user stack!
  324.     public    _ivec31x
  325.     public    _i30x_jump
  326.     public    _i30x_stack
  327.     public    _i30x_sti
  328. _ivec31x:
  329. ; Real mode return - ES:EDI points to structure
  330. ; Set up DS:ESI to point to to our copy
  331.     pushf
  332.     push    ds esi edi ecx
  333.     mov    cx,g_pdata
  334.     mov    ds,cx
  335.     mov    esi,offset DGROUP:_dpmisim_regs
  336.     mov    ecx,21            ; don't update CS:IP or SS:SP
  337.     cld
  338.     rep    movs word ptr es:[edi],word ptr ds:[esi]
  339.     pop    ecx edi esi ds
  340.     popf
  341.     lss    esp,fword ptr cs:_i30x_stack
  342. _i30x_sti    db    ?
  343.     db    66h, 0eah                ; far jmp to 32 bit
  344. _i30x_jump    dd    ?
  345.     dw    ?
  346. _i30x_stack    dd    ?
  347.     dw    ?
  348.     
  349. ENDIF
  350.  
  351.     public    _ivec7
  352. _ivec7:
  353.     push    eax
  354.     mov    eax,cr0
  355.     and    al,0F3h            ; Clear EM & TS bits
  356.     mov    cr0,eax
  357.     pop    eax
  358.     iretd
  359.  
  360.     public    _real_i8
  361. _real_i8:
  362.     int    08h
  363.     iret
  364.     int    09h
  365.     iret
  366.     int    0ah
  367.     iret
  368.     int    0bh
  369.     iret
  370.     int    0ch
  371.     iret
  372.     int    0dh
  373.     iret
  374.     int    0eh
  375.     iret
  376.     int    0fh
  377.     iret
  378.  
  379. ; Improved code by Morten Welinder.  CWS note: We must save bp si di here, 
  380. ; (since called by TC).
  381.  
  382.     public    _generic_handler
  383. _generic_handler:
  384.     push    bp si di
  385.     push    _DPMIsp        ; Needed for RMCB's to be recursive
  386.     mov    _DPMIsp,sp
  387.     sub    _DPMIsp,spare_stack    ; space + extra for HW interrupt
  388.     push    ds
  389.     mov    bx,_tss_ptr
  390.     mov    ax,word ptr [bx].tss_eflags
  391.     and    ax,0011111011010101b        ; user flags
  392.     push    ax
  393.     push    cs
  394.     call    generic1            ; ax, cs, "call" makes iret
  395.     pushf
  396.     cli
  397.     push    ebx
  398.     mov    bx,_tss_ptr
  399.     mov    [bx].tss_eax,eax
  400.     mov    [bx].tss_ecx,ecx
  401.     mov    [bx].tss_edx,edx
  402.     mov    [bx].tss_esi,esi
  403.     mov    [bx].tss_edi,edi
  404.     mov    [bx].tss_ebp,ebp
  405.     pop    dword ptr [bx].tss_ebx
  406.     pop    ax
  407.     mov    dx,0000111011010101b        ; user flags
  408.     mov    cx,word ptr [bx].tss_eflags
  409.     and    ax,dx
  410.     not    dx
  411.     and    cx,dx
  412.     or    ax,cx
  413.     mov    word ptr [bx].tss_eflags,ax
  414.  
  415.     pop    ds
  416.     pop    _DPMIsp
  417.     pop    di si bp
  418.     xor    ax,ax
  419.     retn
  420.  
  421. ; Simulate interrupt call setup (bigger/slower than self modifying code,
  422. ; but I may need it with hw interrupt callbacks)
  423. generic1:
  424.     and    ah,not 2
  425.     push    ax                ; Flags with IF=0
  426.     xor    cx,cx
  427.     mov    es,cx    
  428.     mov    cl,[bx].tss_irqn
  429.     shl    cx,2
  430.     mov    di,cx
  431.     push    dword ptr es:[di]        ; CS:IP of int handler
  432.  
  433. ; DS & ES are undefined -- could use segment translation but don't bother
  434.  
  435.     mov    eax,[bx].tss_eax
  436.     mov    ecx,[bx].tss_ecx
  437.     mov    edx,[bx].tss_edx
  438.     mov    esi,[bx].tss_esi
  439.     mov    edi,[bx].tss_edi
  440.     mov    ebp,[bx].tss_ebp
  441.     mov    ebx,[bx].tss_ebx
  442.  
  443.     iret                    ; Actually an "int tss_irqn"
  444.  
  445.     end_code16
  446.  
  447. ;------------------------------------------------------------------------
  448.  
  449.     end
  450.